/* 
 * File:   fori.cpp
 * Author: Henrique
 * 
 * Created on 22 de Abril de 2010, 13:42
 */

#include <vector>
#include <string>
#include <iostream>

#include "fori.h"
#include "Interpretador.h"
#include "IO.h"

fori::fori() {
}

fori::fori(const fori& orig) {
}

std::string& fori::replaceAll(std::string& context, const std::string& from, const std::string& to) {
    size_t lookHere = 0;
    size_t foundHere;
    while ((foundHere = context.find(from, lookHere)) != std::string::npos) {
        context.replace(foundHere, from.size(), to);
        lookHere = foundHere + to.size();
    }
    return context;
} ///:~

fori::fori(std::string str, double* mem, std::vector<std::string> programa) {
    memoria = mem;
    std::vector<std::string> comandos;

    int inicial = -1;
    int final = -1;
    char varFor = ' ';
    std::string temp;
    int pilha = 0;
    int co = 0;
    for (int i = 0; i < programa.size(); i++) {

        char ch = str.at(str.size() - 1);
        while (ch == ' ' || ch == '\r') {
            str.erase(str.size() - 1, 1);
            ch = str.at(str.size() - 1);

        }
        ch = programa.at(i).at(programa.at(i).size() - 1);
        while (ch == ' ' || ch == '\r') {
            programa.at(i).erase(programa.at(i).size() - 1, 1);
            ch = programa.at(i).at(programa.at(i).size() - 1);

        }
        if (str.compare(programa.at(i)) == 0)
            co = 1;
        if (co == 1) {

            comandos.push_back(programa.at(i));

            if (programa.at(i).find("for") == 0 && !(programa.at(i).compare("endfor") == 0)) {
                pilha++;
            } else
                if (programa.at(i).find("endfor") == 0) {
                pilha--;
            }
            if (pilha == 0)
                break;

        }
    }

    for (int i = 0; i < str.size(); i++) {
        char c = str.at(i);
        if (c != ' ') {
            temp.append(1, c);
        }
    }
    varFor = temp.at(3);
    var = varFor;
    if (temp.find("downto", 0) != std::string::npos) {

        replaceAll(temp, "downto", "|");
        int index = -1;
        for (int i = 0; i < temp.size(); i++) {
            char c = temp.at(i);
            if (c == '|')
                index = i;
        }
        std::string stemp1;
        std::string stemp2;
        for (int i = index - 1; i >= 0; i--) {
            char c = temp.at(i);
            if (isdigit(c)) {
                while (isdigit(c)) {
                    stemp1.insert(0, 1, c);
                    i--;c = temp.at(i);
                }
                inicial = atoi(stemp1.c_str());
                break;
            } else {
                varFor = c;
            }
            inicial = (int) memoria[(int) varFor - (int) 'a'];break;
        }

        for (int i = index + 1; i < temp.size(); i++) {
            char c = temp.at(i);
            if (isdigit(c)) {
                while (isdigit(c)) {
                    stemp2.append(1, c);
                    i++;
                    c = temp.at(i);

                }
                final = atoi(stemp2.c_str());
                break;
            } else {
                final = (int) memoria[(int) varFor - (int) 'a'];
                break;
            }
        }
    } else {
        replaceAll(temp, "to", "|");
        int index = -1;
        for (int i = 0; i < temp.size(); i++) {
            char c = temp.at(i);
            if (c == '|')
                index = i;
        }
        std::string stemp1;
        std::string stemp2;
        for (int i = index - 1; i >= 0; i--) {
            char c = temp.at(i);
            if (isdigit(c)) {
                while (isdigit(c)) {
                    stemp1.insert(0, 1, c);
                    i--;
                    c = temp.at(i);
                }
                inicial = atoi(stemp1.c_str());
                break;
            } else {

                inicial = (int) memoria[(int) varFor - (int) 'a'];
                break;
            }
        }

        for (int i = index + 1; i < temp.size(); i++) {
            char c = temp.at(i);
            if (isdigit(c)) {
                while (isdigit(c)) {
                    stemp2.append(1, c);
                }
                final = atoi(stemp2.c_str());
                break;
            } else
                varFor = c;
            final = (int) memoria[(int) varFor - (int) 'a'];
            break;
        }


    }



    this->posFin = final;
    this->posIni = inicial;
    this->instrucoes = comandos;
}

fori::~fori() {
}

double* fori::executaFor(std::string str) {
    std::vector<std::string> comandos = this->instrucoes;
    comandos.erase(comandos.begin());
    numberCom = comandos.size();
  //  std::cout << posFin << " asasa " << posIni;
    if (str.find("downto", 0) != std::string::npos) {
        for (int i = posIni; i >= posFin; i--) {
            //laco decremento
            Interpretador *interpret = new Interpretador();
            memoria[(int)var - (int) 'a'] = i;
         
            this->memoria = interpret->execute(comandos, this->memoria);
        }
    } else {
        for (int i = posIni; i <= posFin; i++) {
            //laco incremento
            Interpretador *interpret = new Interpretador();
            memoria = interpret->execute(comandos, memoria);
        }
    }
    return memoria;
}

